package cn.online.taxi.common.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Student implements Comparable<Student> {

    private String number;

    private String name;

    private int grades;

    public Student(String number, String name, int grades) {
        this.number = number;
        this.name = name;
        this.grades = grades;
    }

    public Student() {
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getGrades() {
        return grades;
    }

    public void setGrades(int grades) {
        this.grades = grades;
    }

    @Override
    public int compareTo(Student o) {
        return 0;
    }
}

class DNode<T> {

    public T data;

    public DNode<T> prev, next; // 前继指针 后继指针

    public DNode(T data, DNode<T> prev, DNode<T> next) {
        this.data = data;
        this.prev = prev;
        this.next = next;
    }

    public DNode(T data) {
        this(data, null, null);
    }

    public DNode() {
        this(null, null, null);
    }

    public String toString() {
        return this.data.toString();
    }

}

class DoubleLink<T> {

    protected DNode<T> head; //不带数据的头结点
    protected DNode<T> tail; //指向尾部的指针

    public DoubleLink(){
        this.head = this.tail = new DNode<>();          //初始化头结点
    }

    public DoubleLink(T []array) {
        this();
        if(array != null && array.length > 0) {
            this.head.next = new DNode<T>(array[0]);
            tail = this.head.next;
            tail.prev = this.head;
            int i = 1;
            while(i < array.length) {
                tail.next = new DNode<T>(array[i++]);
                tail.next.prev = tail;
                tail = tail.next;
            }
        }
    }

    public boolean add(int index, T data) {
        if(index <= 0 || data == null)
            throw new NullPointerException("index <= 0 || data == null");
        int j = 0;
        DNode<T> front = this.head;
        // 查找要插入结点位置的前一个结点
        while(front.next != null && j < index) {
            j++;
            front = front.next;
        }
        DNode<T> dNode = new DNode<>(data, front, front.next);
        if(front.next != null) {
            front.next.prev = dNode;
        }
        front.next = dNode;
        if(front == this.tail) {
            this.tail = dNode;
        }
        return true;
    }

    public String toString() {
        String str = "";
        DNode<T> pre = this.head.next;
        while(pre != null) {
            str += pre.data;
            pre = pre.next;
            if(pre != null) {
                str += " ";
            }
        }
        return str;
    }

}

class LoopDoubleLink<T> {

    protected DNode<T> head;

    public LoopDoubleLink() {
        this.head = new DNode<>();
        this.head.next = head;
        this.head.prev = head;
    }

    public boolean isEmpty() {
        return this.head.next == head;
    }

    public int length() {

        int length=0;
        DNode<T> p=this.head.next;
        while (p!=this.head){
            length++;
            p=p.next;
        }
        return length;
    }

    public boolean add(T data) {
        if(data==null)
            return false;
        //创建新结点,让前继指针指向head.pre,后继指针指向head
        DNode<T> p=new DNode<>(data,head.prev,head);
        //更新tail后继指针的指向
        this.head.prev.next=p;
        this.head.prev=p;

        return true;
    }

    public T remove(int index) {
        T old = null;
        int size=length();

        if (index<0||index>=size)
            return old;

        int j=0;
        DNode<T> p=this.head.next;

        while (p!=head && j<index)
        {
            j++;
            p = p.next;
        }

        if (p!=head)
        {
            old = p.data;
            p.prev.next = p.next;
            p.next.prev = p.prev;
        }
        return old;
    }

    public String toString() {
        String str = "";
        DNode<T> p = this.head.next;
        while (p != head)
        {
            str += p.data.toString();
            p = p.next;
            if (p != head)
                str += " ";
        }
        return str;
    }

    public List<Student> toAllStudent() {
        List<Student> result = new ArrayList<>();
        DNode<T> p = this.head.next;
        while (p != head)
        {
            result.add((Student) p.data);
            p = p.next;
        }
        return result;
    }

    /**
     * type: 0 学号 1 姓名
     * @param number
     * @param type
     * @return
     */
    public Student toStudentByNumber(String number, int type) {
        Student result = new Student();
        DNode<T> p = this.head.next;
        if (type == 0) {
            while (p != head)
            {
                Student student =  (Student) p.data;
                if(number.equals(student.getNumber())) {
                    result = student;
                }
                p = p.next;
            }
        }else if (type == 1) {
            while (p != head)
            {
                Student student =  (Student) p.data;
                if(number.equals(student.getName())) {
                    result = student;
                }
                p = p.next;
            }
        }

        return result;
    }

    public boolean removeStudentByNumber(String number) {
        List<Student> list = toAllStudent();
        int removeStudentIndex = -1;
        for(Student student : list) {
            if (number.equals(student.getNumber()))
                removeStudentIndex = list.indexOf(student);
        }
        if(removeStudentIndex != -1) {
            remove(removeStudentIndex);
        }
        return true;
    }

}

class SortLoopDoubleLink<T extends Comparable<? extends T>> extends LoopDoubleLink {

    public boolean add(T data) {

        if(data==null||!(data instanceof Comparable))
            throw new NullPointerException("data can\'t be null or data instanceof Comparable must be true");

        Comparable cmp =data;//这里需要转一下类型,否则idea编辑器上检验不通过.

        //如果data值比最后一个结点大,那么直接调用父类方法,在尾部添加.
        if(this.isEmpty() || cmp.compareTo(this.head.prev.data) > 0){
            return super.add(data);
        }

        DNode<T> p=this.head.next;
        //查找插入点
        while (p!=head&&cmp.compareTo(p.data)>0)
            p=p.next;

        DNode<T> q=new DNode<>(data,p.prev,p);
        p.prev.next=q;
        p.prev=q;

        return true;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        boolean flag = true;
        // 初始化数据
        SortLoopDoubleLink<Student> sortLoopDoubleLink = new SortLoopDoubleLink<Student>();
        sortLoopDoubleLink.add(new Student("0733106", "吴兵", 76));
        sortLoopDoubleLink.add(new Student("0733105", "张力", 93));
        sortLoopDoubleLink.add(new Student("0733104", "徐海", 80));
        while(flag) {
            System.out.println("输入insert 插入学生成绩");
            System.out.println("输入delete 删除学生成绩 （按学号删除）");
            System.out.println("输入select 查询成绩");
            System.out.println("输入ls 显示所有学生成绩");
            System.out.println("输入exit 退出");
            String select = sc.next();
            switch (select) {
                case "insert":
                    System.out.println("---插入---");
                    Student student = new Student();
                    System.out.print("学号：");
                    student.setNumber(sc.next());
                    System.out.print("姓名：");
                    student.setName(sc.next());
                    System.out.print("成绩：");
                    student.setGrades(sc.nextInt());
                    sortLoopDoubleLink.add(student);
                    System.out.println("---插入数据成功---");
                    break;
                case "delete":
                    System.out.println("---删除---");
                    System.out.print("学号：");
                    String deleteStuNumber = sc.next();
                    boolean deleteResult = sortLoopDoubleLink.removeStudentByNumber(deleteStuNumber);
                    if(deleteResult)
                        System.out.println("---删除成功---");
                    else
                        System.out.println("---删除失败---");
                    break;
                case "select":
                    System.out.println("---查询---");
                    System.out.println("输入A 按姓名查找  输入B 按学号查询");
                    String selectKey = sc.next();
                    if("A".equals(selectKey)) {
                        System.out.print("姓名：");
                        String selectStuName = sc.next();
                        Student selectStuB = sortLoopDoubleLink.toStudentByNumber(selectStuName, 1);
                        System.out.println(selectStuB.getNumber() + " " + selectStuB.getName() + " " + selectStuB.getGrades());
                        System.out.println("---显示学生信息成功---");
                    }else if("B".equals(selectKey)) {
                        System.out.print("学号：");
                        String selectStuNumber = sc.next();
                        Student selectStuB = sortLoopDoubleLink.toStudentByNumber(selectStuNumber, 0);
                        System.out.println(selectStuB.getNumber() + " " + selectStuB.getName() + " " + selectStuB.getGrades());
                        System.out.println("---显示学生信息成功---");
                    }
                    break;
                case "ls":
                    System.out.println("---显示---");
                    List<Student> stuResult = sortLoopDoubleLink.toAllStudent();
                    for(Student stu : stuResult) {
                        System.out.println(stu.getNumber() + " " + stu.getName() + " " + stu.getGrades() );
                    }
                    System.out.println("---显示所有数据成功---");
                    break;
                case "exit":
                    flag = false;
                    System.out.println("---退出---");
                    break;
                default:
                    break;
            }
        }

        sc.close();
    }
}